package cn.bugstack.springframework.aop;

import org.aopalliance.aop.Advice;

/**
 *  Advisor 接口定义了一个切面（Aspect）的通用概念，它是 Spring AOP 中的关键接口之一。
 *
 *  getAdvice() 方法：该方法用于获取当前切面所包含的通知（Advice）。
 *  通知是切面的核心部分，它定义了在切入点（Pointcut）匹配时要执行的逻辑。
 *  通知可以是不同类型的，比如方法拦截器（MethodInterceptor）、前置通知（BeforeAdvice）、抛出异常通知（ThrowsAdvice）等。
 *  在 Advisor 接口中，getAdvice() 方法返回的就是当前切面所包含的通知对象。
 *
 *  Advice 接口：表示通知的标准接口。它是 Spring AOP 中所有通知类型的基础接口，定义了通知所需的基本行为。
 *  Advice 接口的具体实现类通常是方法拦截器（MethodInterceptor）、前置通知（BeforeAdvice）、抛出异常通知（ThrowsAdvice）等。
 *
 */
public interface Advisor {

    /**
     * Return the advice part of this aspect. An advice may be an
     * interceptor, a before advice, a throws advice, etc.
     * @return the advice that should apply if the pointcut matches
     * @see org.aopalliance.intercept.MethodInterceptor
     * @see BeforeAdvice
     */
    Advice getAdvice();

}

/**
 * 问题：Spring中的Advisor和PointAdvisor接口，以及PointAdvisor接口的实现类AspectJExpressionPointcutAdvisor？
 *
 * 在Spring框架中，Advisor 是用于实现切面（Aspect）的组件，用于将通知（Advice）与切点（Pointcut）组合起来。
 * Advisor 接口是所有切面通知器的基本接口，定义了切面的通用行为。
 *
 * 1. Advisor 接口：
 *      Advisor 接口是 Spring AOP 中所有切面通知器的基本接口。它定义了一个方法 getAdvice()，用于获取与 Advisor 相关联的通知。
 *      Advisor 是切面的基本组成部分，通过将通知和切点组合在一起，实现切面的功能。
 * 2. PointcutAdvisor 接口：
 *      PointcutAdvisor 接口继承了 Advisor 接口，它添加了获取切点的方法 getPointcut()。切点用于定义切面中感兴趣的连接点（Join Point）。
 *      PointcutAdvisor 可以根据切点选择要应用通知的连接点，并将其与通知组合在一起形成切面。
 * 3. AspectJExpressionPointcutAdvisor 类：
 *      AspectJExpressionPointcutAdvisor 是 PointcutAdvisor 接口的一个实现类，它使用 AspectJ 表达式作为切点进行切面编程。
 *      AspectJExpressionPointcutAdvisor 类提供了设置切点表达式和通知的方法，并将它们组合成一个切面。
 *      它可以根据 AspectJ 表达式选择满足条件的连接点，并将通知应用于这些连接点。
 *
 * public class MyApp {
 *     public static void main(String[] args) {
 *         // 创建目标对象
 *         MyService myService = new MyServiceImpl();
 *
 *         // 创建切面
 *         AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
 *         advisor.setExpression("execution(* com.example.MyService.*(..))"); // 设置切点表达式
 *
 *         // 创建通知
 *         MyAdvice myAdvice = new MyAdvice();
 *
 *         // 将切点和通知组合成切面
 *         advisor.setAdvice(myAdvice);
 *
 *         // 创建代理工厂
 *         ProxyFactory proxyFactory = new ProxyFactory();
 *         proxyFactory.setTarget(myService);
 *         proxyFactory.addAdvisor(advisor);
 *
 *         // 获取代理对象
 *         MyService proxy = (MyService) proxyFactory.getProxy();
 *
 *         // 使用代理对象调用方法
 *         proxy.doSomething();
 *     }
 * }
 * 在上述示例中，我们创建了一个 AspectJExpressionPointcutAdvisor，并设置了切点表达式和通知。
 * 然后，我们使用 ProxyFactory 创建代理对象，并将切面添加到代理工厂中。
 * 最后，我们通过代理对象调用方法，切面的通知将在满足切点条件的连接点上被触发执行。
 *
 * 总结：Advisor 是 Spring AOP 中切面通知器的基本接口，PointcutAdvisor 是 Advisor 的子接口，用于获取切点。
 * AspectJExpressionPointcutAdvisor 是 PointcutAdvisor 的一个具体实现类，使用 AspectJ 表达式作为切点，并将通知与切点组合成切面。
 * 它可以根据切点表达式选择满足条件的连接点，并将通知应用于这些连接点。
 *
 * 问题：什么是 AspectJ 表达式？
 *
 * AspectJ 表达式是一种用于定义切点（Pointcut）的语法，它是 AspectJ 框架中的一部分。
 * AspectJ 是一个强大的面向切面编程（AOP）框架，它提供了在 Java 编程语言中实现切面的能力。
 * AspectJ 表达式可以在切面中定义切点，用于选择感兴趣的连接点（Join Point）。
 * 连接点是程序执行过程中的特定位置，如方法调用、方法执行、字段访问等。通过定义切点，可以精确地指定在哪些连接点上应用切面的通知（Advice）。
 *
 * AspectJ 表达式的语法包括以下要素：
 *      1. Execution 表达式：execution(<修饰符模式>? <返回类型模式> <方法名模式>(<参数模式>) <异常模式>?)。
 *      其中，修饰符模式用于匹配方法的修饰符，返回类型模式用于匹配方法的返回类型，方法名模式用于匹配方法名，参数模式用于匹配方法的参数类型，异常模式用于匹配方法抛出的异常类型。
 *      2. Pointcut Designators（切点设计符）：用于选择连接点的一部分，如 execution、call、get、set 等。例如，execution(* com.example.service.*.*(..)) 表示选择 com.example.service 包中所有类的所有方法。
 *      3. Wildcards（通配符）：用于匹配任意字符或一类字符，如 * 表示匹配任意字符序列，.. 表示匹配任意数量的参数。
 *      4. Logical Operators（逻辑运算符）：包括 &&（逻辑与）、||（逻辑或）、!（逻辑非）等，用于组合连接点选择条件。
 *
 * 通过使用 AspectJ 表达式，可以根据需要选择特定的连接点，将切面的通知应用于这些连接点。AspectJ 表达式提供了灵活且强大的语法，可以精确地定义切点，实现精细的切面编程。
 * 下面是一个使用 AspectJ 表达式的示例：
 * @Aspect
 * public class LoggingAspect {
 *     @Before("execution(* com.example.service.*.*(..))")
 *     public void logBefore(JoinPoint joinPoint) {
 *         System.out.println("Before method: " + joinPoint.getSignature().getName());
 *     }
 * }
 * 在上述示例中，使用 AspectJ 表达式 execution(* com.example.service.*.*(..)) 来定义切点，
 * 表示选择 com.example.service 包中所有类的所有方法。@Before 注解将通知应用于满足切点条件的连接点，输出方法调用前的日志信息。

 * 总结：AspectJ 表达式是一种用于定义切点的语法，它可以在切面中精确地选择感兴趣的连接点。
 * AspectJ 表达式使用 Execution 表达式、切点设计符、通配符和逻辑运算符等要素进行构建，提供了灵活且强大的语法，用于实现精细的切面编程。
 */
